package com.miracle.android_voip_simple_demo;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;


import com.tucodec.voip.TYVoipAndroid;
import com.tucodec.voip.VoipImage;
import com.tucodec.voip.TYVoipVideoCapture;
import com.tucodec.voip.TYVoipVideoRender;


/**
 * Created by pan on 2017/12/13.
 */

public class MeetingActivity extends Activity {
    private String ip;
    private int port, mUserId, render1_id, render2_id, render3_id;
    private Boolean mSilentMode = true;
    private TextView toggle_voice_txt;
    private ImageView toggle_speaker_img;
    private LinearLayout toggle_voice, finish_meeting;
    private int screenWidth = 0;
    private int screenHeight = 0;
    private int controlWidth = 0;
    private int controlHeight = 0;
    private int statusHeight = 0;
    private TYVoipVideoRender[] arrayRender = new TYVoipVideoRender[3];
    private int[] location = new int[2];
    /**
     * TYVoipVideoRender 是 VoIP 客户端的视频渲染视图
     * 用于 VoipImage 的显示
     */
    private TYVoipVideoRender mMainRender,render1,render2,render3;

    private TYVoipAndroid mVoIPClient;
    /**
     * VoIP 节点, Key: userId, Value: TYVoipVideoRender
     */
    //VoipRender容器，每个会议室成员userId对应一个VoipRender渲染视图
    private SparseArray<TYVoipVideoRender> mVoIPPeers = new SparseArray<TYVoipVideoRender>();
    private TYVoipVideoCapture mVideoCapture;

    private int mMeetingMemberCount = 1;
    private boolean mSpeakerMode = false;

    //默认使用前置摄像头
    private boolean mUseFrontCamera = true;

    private TYVoipAndroid.VideoCallback mVideoCallback = new TYVoipAndroid.VideoCallback() {
        @Override
        public void renderVoipVideoData(VoipImage voipImage) {

            if (mMeetingMemberCount > 2) {
                //如果image为本地相机返还数据
                if (voipImage.isLocal){
                    //本地预览视频
                    //设置镜像显示
                    //mMainRender.setMirror(false);
                    mMainRender.pushVideoFrame(voipImage);
                }else {
                    //mVoIPPeers.get(voipImage.userId).setMirror(false);
                    mVoIPPeers.get(voipImage.userId).pushVideoFrame(voipImage);
                }

            }else {//1vs1会议
                //如果image为本地相机返还数据
                if (voipImage.isLocal){
                    //render1.setMirror(false);
                    render1.pushVideoFrame(voipImage);
                }else {
                    //本地预览视频
                    //设置镜像显示
                    //mMainRender.setMirror(false);
                    mMainRender.pushVideoFrame(voipImage);
                }

            }
        }
//        //摄像机回调，本地视图预览
//        @Override
//        public void previewImage(VoipImage voipImage) {
//            // 本地预览视频
//            //设置镜像显示
//            mMainRender.setMirror(false);
//            mMainRender.pushVideoFrame(voipImage);
//        }
//        //网络视频传输,获取每一帧视图的userId，并渲染到对应视图上
//        @Override
//        public void decodedImage(VoipImage voipImage) {
//            if (voipImage.userId!=mUserId){
//                mVoIPPeers.get(voipImage.userId).setMirror(false);
//                mVoIPPeers.get(voipImage.userId).pushVideoFrame(voipImage);
//            }
//        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_meeting);
        initView();  //Init UI of meeting room, init Views, set mute voice Click event and quit room button click event.
        getValue();  //Get the value of IP, Port, UserId which is from last Activity.
        setClick();  //Click render on the screen
        initGroupChat();
        putRender();
    }

    private void initView() {
        mMainRender = findViewById(R.id.meeting_view);
        render1 = findViewById(R.id.Member_render1);
        render2 = findViewById(R.id.Member_render2);
        render3 = findViewById(R.id.Member_render3);

        toggle_voice_txt = findViewById(R.id.toggle_voice_txt);
        toggle_voice = findViewById(R.id.toggle_voice);
        toggle_voice.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!mSilentMode) {
                    //取消静音
                    mVoIPClient.unmuteMicrophone();
                    toggle_voice_txt.setText("静音");
                } else {
                    //静音
                    mVoIPClient.muteMicrophone();
                    toggle_voice_txt.setText("取消静音");
                }
                mSilentMode = !mSilentMode;
            }
        });
        finish_meeting = findViewById(R.id.finish_meeting);
        finish_meeting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        toggle_speaker_img = findViewById(R.id.toggle_speaker_img);
        LinearLayout toggle_speaker = findViewById(R.id.toggle_speaker);
        toggle_speaker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!mSpeakerMode) {
                    toggle_speaker_img.setImageResource (R.mipmap.ic_voipspeakeron);
                } else {
                    toggle_speaker_img.setImageResource(R.mipmap.ic_voipspeakeroff);
                }
                mSpeakerMode = !mSpeakerMode;
                toggleSpeaker(mSpeakerMode);
            }
        });

        LinearLayout toggle_switch_cam = findViewById(R.id.switch_cam);
        toggle_switch_cam.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                mVideoCapture.stop();
                mUseFrontCamera = !mUseFrontCamera;
                if (mMeetingMemberCount > 2) {
                    mVideoCapture.start(mUseFrontCamera, mVoIPClient.getConfig(), (ViewGroup) mMainRender.getParent());
                }else {
                    mVideoCapture.start(mUseFrontCamera, mVoIPClient.getConfig(), (ViewGroup) render1.getParent());

                    if (mUseFrontCamera) mVideoCapture.setRotation(3);
                    else mVideoCapture.setRotation(1);
                }
            }
        });



    }

    private void getValue() {
        Intent intent = getIntent();
        ip = intent.getStringExtra("ip");
        port = intent.getIntExtra("port",0);
        mUserId = intent.getIntExtra("userid",0);
        render1_id = intent.getIntExtra("render1_id",0);
        render2_id = intent.getIntExtra("render2_id",0);
        render3_id = intent.getIntExtra("render3_id",0);

        if (render1_id > 0) mMeetingMemberCount++;
        if (render2_id > 0) mMeetingMemberCount++;
        if (render3_id > 0) mMeetingMemberCount++;
    }

    private void setClick(){
        arrayRender[0] = render1;
        arrayRender[1] = render2;
        arrayRender[2] = render3;
        //点击事件，放大缩小render
        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
        screenWidth = outMetrics.widthPixels;
        screenHeight = outMetrics.heightPixels;

        ConstraintLayout.LayoutParams params_meeting = (ConstraintLayout.LayoutParams) mMainRender.getLayoutParams();
        params_meeting.width = screenWidth;
        params_meeting.height = screenHeight;
        mMainRender.setLayoutParams(params_meeting);

        mMainRender.setBackground(null);
        controlWidth  = DensityUtil.dip2px(this,150f);
        controlHeight = DensityUtil.dip2px(this,100f);
        statusHeight = getStatusBarHeight();
        render1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                exchangeRenderLocation(0);
            }
        });
        render2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                exchangeRenderLocation(1);
            }
        });
        render3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                exchangeRenderLocation(2);
            }
        });
    }

    private void initGroupChat() {

        TucodeC appCore = (TucodeC)getApplication();
        mVoIPClient = appCore.getSingleVoipInstance();

         /**
         * @param callback  TYVoipAndroid 对象
         * @param param    视频捕捉参数
         */
        //初始化本地摄像头
        mVideoCapture = new TYVoipVideoCapture(mVoIPClient,
                new TYVoipVideoCapture.CaptureParam(mVoIPClient.getConfig().videoWidth,
                        mVoIPClient.getConfig().videoHeight));

        /**
         * 打开本地视频捕捉设备
         * @param frontCamera 是否使用前置摄像头
         * @param config      VoIP 配置信息
         * @param parentView  用于包含
         * @return error code  0: 成功
         * -1: 相机无法启动
         * -2: 相机被禁用
         * -3: 打开相机失败
         * -4: 没有相机权限
         */
        if (mMeetingMemberCount > 2)
            mVideoCapture.start(mUseFrontCamera, mVoIPClient.getConfig(), (ViewGroup)mMainRender.getParent());
        else
            mVideoCapture.start(mUseFrontCamera, mVoIPClient.getConfig(), (ViewGroup)render1.getParent());

        /**
         * 注册音视频回调
         */
        mVoIPClient.registerVideoCallback(mVideoCallback);

        mVoIPClient.registerAudioCallback(mAudioCallback);

        /**
         * 初始化 VoIP 客户端
         * @param videoCapture video capture object used to open/close camera
         */
        mVoIPClient.initVoip(mVideoCapture);

        /**
         * @param videoBitRate 视频码率
         * @param audioBitRate 音频码率
         * @param userid userId
         */
        //通知转发服务器已准备好上传本地视频流以及下拉他人视频流，注意userId需要先登录
        mVoIPClient.startVoip(1024, 16000,mUserId);

        /**
         * @param rotation 视频旋转角度，默认为0
         * 参数为0、1、2、3，传错认为传0
         * 分别对应0度、90度、180度、270度，用来调节横竖屏
         */
        mVideoCapture.setRotation(3);
        /**
         * @param gain 声音大小 0~100
         * 默认为50，可调节
         * 传错值默认传入50
         */
        mVoIPClient.setSpeakerGain(50);
        //打开关闭扬声器，注意需要在XML里写入权限
        toggleSpeaker(false);
    }

    /**
     * 免提
     *
     * @param on
     */
    private void toggleSpeaker(boolean on) {
        AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
        if(on) {
            audioManager.setSpeakerphoneOn(true);
        } else {
            audioManager.setSpeakerphoneOn(false);//关闭扬声器
            audioManager.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
            setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
            //把声音设定成Earpiece（听筒）出来，设定为正在通话中
            audioManager.setMode(AudioManager.MODE_IN_CALL);
        }
    }

    private void putRender() {

        //多人会议，主屏mainRender显示本人
            if (render1_id != 0) {
                mVoIPPeers.put(render1_id, render1);
                render1.setVisibility(View.VISIBLE);
                //设置render1在最上方显示
                render1.setZOrderOnTop(true);
                //add对方userId，下拉对方视频流，注意：此时对端也要add你的节点，才能达到相互通信的目的，否则只能单方面接受数据
                //VideoCallback会回调渲染好的视频帧，渲染到对应Render上
                mVoIPClient.addClientNode(render1_id);
                //注意：此Demo只演示了如何add节点，当对端结束通话，
                // 应当调用mVoIPClient.removeClientNode(other_userId)，通知转发服务器结束下拉该对端视频流；
                // 并做视图隐藏等对应操作；
            }
            if (render2_id != 0) {
                mVoIPPeers.put(render2_id, render2);
                render2.setVisibility(View.VISIBLE);
                render2.setZOrderOnTop(true);
                mVoIPClient.addClientNode(render2_id);
            }
            if (render3_id != 0) {
                mVoIPPeers.put(render3_id, render3);
                render3.setVisibility(View.VISIBLE);
                render3.setZOrderOnTop(true);
                mVoIPClient.addClientNode(render3_id);
            }

    }

    //No useful
    private TYVoipAndroid.AudioCallback mAudioCallback = new TYVoipAndroid.AudioCallback() {
        @Override
        public void audioNotification(int i) {
        }
    };

    //获取状态栏高度
    private int getStatusBarHeight() {
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    //显示缩小 Member_render
    private void exchangeRenderLocation(int i){
        if (arrayRender[i].getWidth() !=screenWidth){
            arrayRender[i].getLocationOnScreen(location);
            for (int s = 0;s<i;s++){
                arrayRender[s].setVisibility(View.INVISIBLE);
                Log.i("voip_android", "exchangeRenderLocation arrayRender[${i}] = GONE");
            }
            ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) arrayRender[i].getLayoutParams();
            params.width = screenWidth;
            params.height = screenHeight;
            arrayRender[i].setLayoutParams(params);
        }else{
            for (int s = 0;s<i;s++){
                arrayRender[s].setVisibility(View.VISIBLE);
            }
            ConstraintLayout.LayoutParams params_meeting = (ConstraintLayout.LayoutParams) arrayRender[i].getLayoutParams();
            params_meeting.width = controlWidth;
            params_meeting.height = controlHeight;
            params_meeting.setMargins(location[0],location[1]-i*controlHeight-statusHeight,0,0);
            arrayRender[i].setLayoutParams(params_meeting);
        }
    }

    private void releaseCall() {
        //清空该userId add的所有节点，相当于逐个remove
        mVoIPClient.clearClientNodeList();
        // 退出会议室
        //停止相机视频捕捉
        mVideoCapture.stop();
        //结束Voip通话
        mVoIPClient.stopCall();
        //释放资源
        mVoIPClient.release();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseCall();
    }

}
